package com.example.drawtexttobitmap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Region;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by Alex-Zhang on 2017/11/26.
 */

public class PhotoFrameView extends View {

    private int DEFAULT_WIDTH = 720;

    private int DEFAULT_HEIGHT = 1280;

    private float rectWidth = 300;
    private float rectHeight = 300;

    private int mDimmedColor;
    private RectF mRectF;
    private Paint mPaint;

    private Bitmap bitmap;
    private RectF bRect;
    private float newRatio;
    private Matrix mMatrix;
    private Paint cPaint;
    private Canvas mCanvas;


    public PhotoFrameView(Context context) {
        super(context);
        init();
    }

    public PhotoFrameView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PhotoFrameView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mDimmedColor = Color.argb(120, 200, 255, 255);
        mRectF = new RectF();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.GRAY);
        // mPaint.setStrokeWidth(5);
        bRect = new RectF();

        cPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        cPaint.setColor(Color.BLUE);
        cPaint.setStrokeWidth(cornerStrokeWidth);
        mCanvas = new Canvas();
    }

    public void setBitmap(Bitmap bitmap) {
        this.rawBitmap = bitmap;
        if (calculationBitmapRatio(rawBitmap) != null) {
            this.bitmap =calculationBitmapRatio(rawBitmap);
        }
        if (this.bitmap != null) {
            bRect.set(mRectF.left + (mRectF.width() / 2 - this.bitmap.getWidth() / 2), (float) (getHeight() - this.bitmap.getHeight()) / 2, mRectF.left + this.bitmap.getWidth(),
                    (float) (getHeight() - this.bitmap.getHeight()) / 2 + this.bitmap.getHeight());
        }
        invalidate();
    }

    int index;

    Bitmap rawBitmap;
    Bitmap rawRotationBitmap;

    public void rotationBitmap() {
        mMatrix = new Matrix();

        mMatrix.setRotate(90 * ++index);
        rawRotationBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.getWidth(), rawBitmap.getHeight(), mMatrix, false);
        Log.d("rotationBitmap", ": " + (90 * index));
        Bitmap scaledBitmap = Bitmap.createScaledBitmap(rawBitmap, rawBitmap.getWidth(), rawBitmap.getHeight(), true);
        Bitmap rotationBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), mMatrix, false);
        bitmap = calculationBitmapRatio(rotationBitmap);
        bRect.set(mRectF.left + (mRectF.width() / 2 - bitmap.getWidth() / 2), (float) (getHeight() - bitmap.getHeight()) / 2, mRectF.left + bitmap.getWidth(),
                (float) (getHeight() - bitmap.getHeight()) / 2 + bitmap.getHeight());
        distanceY = 0;
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST) {
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_WIDTH, MeasureSpec.EXACTLY);
        }
        if (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_HEIGHT, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mRectF.set((float) w / 2 - rectWidth / 2, (float) h / 2 - rectHeight / 2,
                (float) w / 2 + rectWidth / 2, (float) h / 2 + rectHeight / 2);
        if (this.rawBitmap != null)
        {
            setBitmap(this.rawBitmap);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawPhoto(canvas);
        drawLayer(canvas);
        drawBounds(canvas);
    }

    private void drawPhoto(Canvas canvas) {
        if (bitmap != null) {
            canvas.drawBitmap(bitmap, bRect.left, bRect.top, null);
        }
    }

    private void drawBounds(Canvas canvas) {
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(mRectF, mPaint);
        mPaint.reset();
        // mPaint.setStrokeWidth(10);
        // canvas.drawRect(mRectF.left - borderWidth, mRectF.top - borderWidth, mRectF.left - borderWidth + borderHeight, mRectF.left, mPaint);
        drawRectCorner(canvas,mRectF,cPaint);
    }
    float cornerStrokeWidth = 5;
    float cornerLength = 30;
    private void drawRectCorner(Canvas canvas, RectF rectF, Paint paint) {
        canvas.drawLine(rectF.left - cornerStrokeWidth / 2, rectF.top, rectF.left + cornerLength, rectF.top, paint);
        canvas.drawLine(rectF.left, rectF.top - cornerStrokeWidth / 2, rectF.left, rectF.top + cornerLength, paint);
        canvas.drawLine(rectF.left - cornerStrokeWidth / 2, rectF.bottom, rectF.left + cornerLength, rectF.bottom, paint);
        canvas.drawLine(rectF.left, rectF.bottom + cornerStrokeWidth / 2, rectF.left, rectF.bottom - cornerLength, paint);
        canvas.drawLine(rectF.right + cornerStrokeWidth / 2, rectF.top, rectF.right - cornerLength, rectF.top, paint);
        canvas.drawLine(rectF.right, rectF.top - cornerStrokeWidth / 2, rectF.right, rectF.top + cornerLength, paint);
        canvas.drawLine(rectF.right + cornerStrokeWidth / 2, rectF.bottom, rectF.right - cornerLength, rectF.bottom, paint);
        canvas.drawLine(rectF.right, rectF.bottom + cornerStrokeWidth / 2, rectF.right, rectF.bottom - cornerLength, paint);
    }


    private void drawLayer(Canvas canvas) {
        canvas.save();
        canvas.clipRect(mRectF, Region.Op.DIFFERENCE);
        canvas.drawColor(mDimmedColor);
        canvas.restore();
    }

    float startY;

    float distanceY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (isRect(event)) {
                    startY = event.getY();
                }
                break;

            case MotionEvent.ACTION_MOVE:
                if (isRect(event)) {
                    float dy = event.getY() - startY;
                    distanceY += dy;
                    if (isCanDrag()) {
                        bRect.set(mRectF.left, (float) (getHeight() - bitmap.getHeight()) / 2 + distanceY, mRectF.left + bitmap.getWidth(),
                                (float) (getHeight() - bitmap.getHeight()) / 2 + distanceY + bitmap.getHeight());
                    } else {
                        distanceY -= dy;
                    }
                    invalidate();
                }
                startY = event.getY();
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                startY = 0;
                break;
        }
        return true;
    }

    private boolean isRect(MotionEvent event) {
        return bRect.contains(event.getX(), event.getY());
    }

    private boolean isCanDrag() {
        return (0 <= distanceY && distanceY <= mRectF.top - (float) (getHeight() - bitmap.getHeight()) / 2)
                || (distanceY <= 0 && distanceY >= mRectF.bottom - (float) (getHeight() - bitmap.getHeight()) / 2 - bitmap.getHeight());
    }

    private Bitmap calculationBitmapRatio(Bitmap bitmap) {
        int desireWidth;
        int desireHeight;
        if (mRectF.left > 0){
            desireWidth = (int) mRectF.width();
            newRatio = ((float) desireWidth) / (float) bitmap.getWidth();
            desireHeight = (int) (bitmap.getHeight() * newRatio);
            return Bitmap.createScaledBitmap(bitmap, desireWidth, desireHeight, false);
        }
        return null;
    }

    public Bitmap createBitmap() {
        int height = (int) (mRectF.height() * (1 / newRatio));
        Bitmap bitmapParent = Bitmap.createBitmap(rawBitmap.getWidth(), height, Bitmap.Config.ARGB_8888);
       mCanvas.setBitmap(bitmapParent);
        Bitmap bitmap1;
        int bitmapY = (int) ((int) (mRectF.top - (float) (getHeight() - this.bitmap.getHeight()) / 2) - distanceY);
        if ((float) this.bitmap.getWidth() / (float) this.bitmap.getHeight() > mRectF.height() / mRectF.width()) {
            if (mMatrix == null) {
                bitmap1 = Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.getWidth(), rawBitmap.getHeight(), null, true);
            } else {
                bitmap1 = Bitmap.createBitmap(rawRotationBitmap, 0, 0, rawRotationBitmap.getWidth(), rawRotationBitmap.getHeight(), null, true);
            }
            mCanvas.drawBitmap(bitmap1, 0, (bitmapParent.getHeight() - bitmap1.getHeight()) >> 1, null);
            return bitmapParent;
        } else {
            return Bitmap.createBitmap(rawRotationBitmap, 0, (int) (bitmapY * (1 / newRatio)),
                    rawRotationBitmap.getWidth(), height);
        }
    }
}

